<template>
  <content100>
    <card100>
      <div slot="header" class="card-header">
        <span>功能菜单管理</span>
        <div>
          <import-menu :fn-import="fnImportMenu" />
          <a ref="export" :href="urlExport" style="display:none;" />
          <el-button type="success" class="btn" @click="handleExport">导出菜单</el-button>
          <page-scanner @scanComplete="handleScanComplete" />
        </div>
      </div>
      <el-tree
        ref="menu"
        :data="data"
        node-key="id"
        default-expand-all
        :expand-on-click-node="false"
        draggable
        :allow-drop="allowDrop"
        :allow-drag="allowDrag"
        @node-drop="handleDrop"
      >
        <span slot-scope="{ node }" class="custom-tree-node">
          <span>
            <svg-icon v-if="node.data.meta && node.data.meta.icon && node.data.meta.icon !== ''" class="icon el-select" :icon-class="node.data.meta.icon" />
            <span>{{ node.label }}</span>
            <span v-if="node['data']['lost']" class="lost">&lt;{{ node['data'].component }}&gt;</span>
            <span v-else>
              &lt;{{ node['data'].component }}&gt;
              <el-button v-if="node['data']['component'] !== 'Layout'" type="text" icon="el-icon-document-copy" title="复制 path" size="mini" @click="handleClipboard(node['data']['component'], $event)" />
            </span>
            <span v-if="node['data'].custom" style="color: blue;"> - {{ node['data'].custom }}</span>
          </span>
          <span>
            <span>
              <svg-icon v-if="node['data'].props.admin" icon-class="admin" />
              <svg-icon v-if="node['data'].hidden" icon-class="hidden" />
            </span>
            <span style="margin-left: 50px;">
              <tree-button
                v-if="node['data'].component === 'Layout'"
                title="添加下级菜单"
                type="primary"
                icon="add-child"
                @click="() => appendChild(node['data'])"
              />
              <tree-button v-else />
              <tree-button
                v-if="node['data']['id']"
                title="编辑菜单"
                type="success"
                icon="edit"
                @click="() => editMenu(node['data'])"
              />
              <tree-button v-else />
              <tree-button
                v-if="node['data']['id'] && (node['data']['parent']['component'] === 'Layout' || node['data']['lost'])"
                title="删除菜单"
                type="danger"
                icon="delete"
                @click="() => handleRemove(node, node['data'])"
              />
              <tree-button v-else />
            </span>
          </span>
        </span>
      </el-tree>
    </card100>
    <func-menu-info ref="dlgAddMenu" :fn="fnAddMenu" @saved="handleFuncSave" />
    <func-menu-info ref="dlgEditMenu" :fn="fnEditMenu" @saved="handleFuncSave" />
    <menu-type ref="dlgType" v-model="reloadMenuTypes" @select="handleNewMenu" />
    <delete-menu ref="dlgDelete" :fn="fmDeleteMeun" @delete="handleDeleted" />
  </content100>
</template>

<script>
import PageScanner from './refresh/index'
import ImportMenu from './ImportMenu'
import { getMenuTree, addMenu, updateMenu, deleteMenu, updateMenuOrder, exportMenus, importMenus } from '@/svc/funcs'
import MenuType from './MenuType'
import FuncMenuInfo from './FuncMenuInfo'
import DeleteMenu from './DeleteMenu'
import TreeButton from './TreeButton'
import clipboard from '@/utils/clipboard'

export default {
  name: 'FuncAndMenu',
  components: { PageScanner, MenuType, FuncMenuInfo, DeleteMenu, TreeButton, ImportMenu },
  data() {
    return {
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      data: [],
      currentParent: null,
      currentNode: null,
      saving: false,
      reloadMenuTypes: true,
      fnAddMenu: addMenu.fn,
      fnEditMenu: updateMenu.fn,
      fmDeleteMeun: deleteMenu.fn,
      fnImportMenu: importMenus.fn,
      urlExport: exportMenus.fn()
      // showTypeMenu: false
    }
  },
  mounted() {
    this.loadMenus()
  },
  methods: {
    loadMenus() {
      getMenuTree.fn(this).then(res => {
        // 全部标记顺序，不需要回调报告
        res['id'] = ''
        this.tagChildrenIndex(res, true)
        this.data = [res]
      })
    },
    tagChildrenIndex(node, rescure, reportChangeFn) {
      if (node.children) {
        node.children.forEach((item, index) => {
          if (item['index'] !== index || (!item['parent']) || item['parent']['id'] !== node['id']) {
            // 顺序不一致
            if (reportChangeFn) { // 回调函数
              reportChangeFn(item, index, node)
            }
          }
          // console.log('index', index)
          item['parent'] = node
          item['index'] = index
          if (rescure) { // 递归
            // console.log('index1', index)
            this.tagChildrenIndex(item, rescure, reportChangeFn)
          }
        })
      }
    },
    handleNewMenu(page) {
      // 添加菜单
      this.$refs.dlgAddMenu.showAdd(this.currentParent['id'], page)
    },
    appendChild(parent) {
      this.currentParent = parent
      this.$refs.dlgType.show()
    },
    editMenu(menuData) {
      // this.currentMenu = menuData
      this.$refs.dlgEditMenu.showEdit(menuData)
    },
    handleFuncSave(add, res) {
      if (add) {
        // 添加
        if (res['children']) {
          res['children'].forEach(item => {
            item['parent'] = res
          })
        }
        res['parent'] = this.currentParent
        if (!this.currentParent.children) {
          this.currentParent.children = [res]
        } else {
          this.currentParent.children.push(res)
        }
        this.reloadMenuTypes = true
      } else {
        // 修改
        this.replaceNode(this.data[0], res)
      }
    },
    replaceNode(parent, newData) {
      if (parent.children) {
        for (let n = 0; n < parent.children.length; n++) {
          const child = parent.children[n]
          if (this.replaceNode(child, newData)) {
            return true
          }
          if (child['id'] === newData['id']) {
            newData['children'] = child['children']
            newData['parent'] = child['parent']
            this.$set(parent.children, n, newData)
            return true
          }
        }
      }
      return false
    },
    handleDrop(draggingNode, dropNode, dropType, event) {
      const param = []
      const nodeMap = {}
      const fn = (node, index, parent) => {
        if (!nodeMap[node['id']]) {
          param.push({
            id: node['id'],
            title: node['label'],
            parentId: parent['id'],
            order: index
          })
          nodeMap[node['id']] = true
        }
      }
      this.tagChildrenIndex(draggingNode['data']['parent'], false, fn)
      const reindexTarget = dropType === 'inner' ? dropNode['data'] : dropNode['data']['parent']
      this.tagChildrenIndex(reindexTarget, false, fn)
      updateMenuOrder.fn(this, param).then(res => {
        this.menuReOrder = false
        this.$success('菜单位置更新完成')
      }).catch(() => {
        this.loadMenus()
      })
    },
    handleRemove(node, data) {
      this.currentParent = node['parent']
      this.$refs.dlgDelete.show(node['data'])
    },
    handleDeleted(id) {
      const children = this.currentParent.data['children']
      if (children) {
        for (let n = 0; n < children.length; n++) {
          if (children[n]['id'] === id) {
            children.splice(n, 1)
            break
          }
        }
      }
      this.reloadMenuTypes = true
    },
    handleScanComplete() {
      this.reloadMenuTypes = true
    },
    allowDrop(draggingNode, dropNode, type) {
      return (dropNode.data.label !== 'ROOT') && // 非 ROOT 节点
        (dropNode.data.component === 'Layout' || type !== 'inner') && // Layout 节点，非 Layout 节点的 before 和 after
        (dropNode.data.parent.component === 'Layout') //
    },
    allowDrag(draggingNode) {
      const dd = draggingNode['data']
      const dpd = dd['parent']
      // console.log(draggingNode, draggingNode.parent)
      return dd.label !== 'ROOT' &&
        dpd.component === 'Layout'
    },
    handleClipboard(text, event) {
      clipboard(text, event)
    },
    handleExport() {
      console.log(this.urlExport)
      // this.$refs.export.url =
      this.$refs.export.click()
    }
  }
}
</script>

<style scoped>
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
.lost {
  text-decoration: line-through;
}
</style>
